<template>
  <view
    class="cell"
    :style="[getStyle]"
    :class="[
      `cell--${getSize}`,
      `cell--sub-${getSubSize}`,
      {
        'cell--inset': getInset,
        'cell--box-shadow': shadowable,
        'cell--sub-desc': subDesc,
        'cell--border': getBorder,
        'cell--round': getRound,
      },
    ]"
    @tap="handleClick"
  >
    <view class="cell__inner" :style="{ 'align-items': align, display: $slots.default && !flex ? 'block' : 'flex' }">
      <slot>
        <view
          v-if="$slots.label || label"
          class="cell__label"
          :class="{ bold: getWeight === 'label', 'cell__label--tip': labelTip }"
        >
          <slot v-if="$slots.label" name="label" />
          <template v-else> {{ $t(label) }}</template>
        </view>
        <view v-if="$slots.icon || icon" class="cell__icon" :style="{ height: getIconSize + 'rpx' }">
          <m-badge :value="badge" :show="badge !== '' && badgePosition === 'icon'">
            <slot v-if="$slots.icon" name="icon" :item="item" />
            <m-icon v-else-if="icon" :name="icon" :size="getIconSize" class="icon" color="inherit" />
          </m-badge>
        </view>
        <view class="cell__title-group">
          <view
            v-if="title || $slots.center"
            class="title"
            :class="{ bold: getWeight === 'title' }"
            :style="{ 'align-items': align, color: getTitleColor }"
          >
            <m-badge v-if="title" :value="badge" position="after" :show="badge !== '' && badgePosition === 'title'">
              {{ $t(title) }}
            </m-badge>
            <view v-if="$slots.center" class="center" :class="[{ 'center--right': centerRight }]">
              <slot name="center" />
            </view>
          </view>
          <view
            v-if="subTitle"
            class="sub-title"
            :class="[`sub-title--${subTitleSize}`, { bold: getWeight === 'subTitle' }]"
            :style="[getSubTitleStyle]"
          >
            <rich-text :nodes="subTitle" />
            <view v-if="$slots.sub" class="sub">
              <slot name="sub" />
            </view>
            <m-icon v-if="subTitleIcon" :name="subTitleIcon" :size="24" class="cell__sub-title-icon" color="inherit" />
          </view>
        </view>
        <view
          v-if="desc || $slots.desc || subDesc || $slots.subDesc || $scopedSlots.desc"
          class="cell__desc"
          :style="{ 'text-align': descTextAlign }"
        >
          <view
            v-if="desc || $slots.desc || $scopedSlots.desc"
            class="desc"
            :class="{ bold: getWeight === 'desc' }"
            :style="[getDescStyle]"
          >
            <slot v-if="$slots.desc || $scopedSlots.desc" name="desc" :item="item" />
            <template v-else>
              {{ $t(desc) }}
            </template>
          </view>
          <view v-if="subDesc || $slots.subDesc" class="sub-desc" :class="{ bold: getWeight === 'subDesc' }">
            <slot v-if="$slots.subDesc" name="subDesc" />
            <template v-else>
              {{ $t(subDesc) }}
            </template>
          </view>
        </view>
        <slot v-if="$slots['link']" name="link" :item="item" />
        <m-icon v-if="isLink || to" name="arrow-right" :size="24" :color="getColor" />
      </slot>
    </view>
  </view>
</template>

<script lang="ts">
import { defineComponent, PropType, computed, inject } from '@vue/composition-api'
import { useRouter } from '@/hooks'
import settings from '@/settings'
import addColor from '@/utils/add-color'
import addUnit from '@/utils/add-unit'

export type CellDescTextAlign = 'left' | 'center' | 'right'
export type CellSize = 'xl' | 'lg' | 'md' | 'sm' | 'xs'

export default defineComponent({
  props: {
    // 标题名称
    title: {
      type: [String, Number],
      default: '',
    },
    // 左侧副标题
    subTitle: {
      type: [String, Number],
      default: '',
    },
    // 右侧描述
    desc: {
      type: [String, Number],
      default: '',
    },
    // 右侧描述文本对齐方式 text-align
    descTextAlign: {
      type: String as PropType<CellDescTextAlign>,
      default: 'right',
    },
    // 是否展示右侧箭头并开启点击反馈
    isLink: {
      type: Boolean,
      default: false,
    },
    // 左侧 图标名称 或图片链接
    icon: {
      type: String,
      default: '',
    },
    // 圆角半径
    roundRadius: {
      type: [Number, String],
      default: 12,
    },
    boxShadowVal: {
      type: String,
      default: '',
    },
    // 点击后跳转的目标路由对象，同 vue-router 的 to 属性 属性
    to: {
      type: Object,
      default: null,
    },
    // 是否在跳转时替换当前页面历史
    replace: {
      type: Boolean,
      default: false,
    },
    inset: {
      type: Boolean,
      default: null,
    },
    size: {
      type: String as PropType<CellSize>,
      default: null, // sm md lg
    },
    subTitleSize: {
      type: String as PropType<CellSize>,
      default: 'md', // sm
    },
    label: {
      type: String,
      default: '',
    },
    subTitleIcon: {
      type: String,
      default: '',
    },
    subDesc: {
      type: String,
      default: '',
    },
    iconSize: {
      type: [String, Number],
      default: null,
    },
    badge: {
      type: [String, Number],
      default: '', // '.' number
    },
    badgePosition: {
      type: String,
      default: 'title',
    },
    align: {
      type: String,
      default: 'center',
    },
    border: {
      type: Boolean,
      default: null,
    },
    weight: {
      type: String,
      default: null,
    },
    subSize: {
      type: String,
      default: null,
    },
    subTitleColor: {
      type: String,
      default: '',
    },
    descColor: {
      type: String,
      default: '',
    },
    item: {
      type: Object,
      default: () => ({}),
    },
    round: {
      type: Boolean,
      default: null,
    },
    padding: {
      type: String,
      default: null,
    },
    // 作用上下间距
    margin: {
      type: String,
      default: null,
    },
    labelTip: {
      type: Boolean,
      default: false,
    },
    shadowable: {
      type: Boolean,
      default: false,
    },
    marginBottom: {
      type: String,
      default: null,
    },
    centerRight: {
      type: Boolean,
      default: false,
    },
    flex: {
      type: Boolean,
      default: false,
    },
    color: {
      type: String,
      default: '#666',
    },
    titleColor: {
      type: String,
      default: '',
    },
    bg: {
      type: String,
      default: null,
    },
  },
  emit: ['click'],
  options: {
    virtualHost: true, //  将自定义节点设置成虚拟的，更加接近Vue组件的表现。我们不希望自定义组件的这个节点本身可以设置样式、响应 flex 布局等，而是希望自定义组件内部的第一层节点能够响应 flex 布局或者样式由自定义组件本身完全决定
  },
  setup(props, { emit }) {
    const { to, replace, roundRadius, boxShadowVal } = props
    const cellParent: any = inject('cellParent', null)
    const router: any = useRouter()
    const handleClick = (e) => {
      if (to) {
        const routerName = to && (to.name as string)
        if (['Index', 'Category', 'Community', 'Mine', 'Cart'].includes(routerName)) {
          router.pushTab(to)
        } else {
          router[replace ? 'replace' : 'push'](to)
        }
      }
      emit('click', e)
    }
    const getTitleColor = computed(() => {
      return props.titleColor
    })
    const getStyle = computed(() => {
      const obj: any = {
        borderRadius: uni.upx2px(+roundRadius) + 'px',
        boxShadow: boxShadowVal,
      }

      if (props.padding !== null) {
        obj.padding = props.padding
      }

      if (props.margin !== null) {
        obj.marginTop = addUnit(props.margin)
        obj.marginBottom = addUnit(props.margin)
      }
      if (props.marginBottom !== null) {
        obj.marginBottom = addUnit(props.marginBottom)
      }
      if (props.bg !== null) {
        obj.background = props.bg
      }

      return obj
    })

    const getIconSize = computed(() => {
      if (props.iconSize != null) {
        return props.iconSize
      }

      if (cellParent) {
        return cellParent.iconSize
      }

      return 40
    })

    const getBorder = computed(() => {
      if (props.border != null) {
        return props.border
      }

      if (cellParent) {
        return cellParent.border
      }

      return false
    })

    const getSize = computed(() => {
      if (props.size != null) {
        return props.size
      }

      if (cellParent) {
        return cellParent.size
      }

      return 'md'
    })

    const getWeight = computed(() => {
      if (props.weight != null) {
        return props.weight
      }

      if (cellParent) {
        return cellParent.weight
      }

      return ''
    })

    const getSubSize = computed(() => {
      if (props.subSize != null) {
        return props.subSize
      }

      if (cellParent) {
        return cellParent.subSize
      }

      return 'md'
    })

    const getSubTitleStyle = computed(() => {
      return {
        color: addColor(props.subTitleColor || ''),
      }
    })
    const getDescStyle = computed(() => {
      return {
        color: addColor(props.descColor || ''),
      }
    })

    const getRound = computed(() => {
      if (props.round != null) {
        return props.round
      }

      if (cellParent) {
        return cellParent.round
      }

      return false
    })

    const getInset = computed(() => {
      if (props.inset !== null) {
        return props.inset
      }

      return settings.css['--card-style'] === 'card'
    })
    const getColor = computed(() => {
      return settings.css[props.color]
    })
    return {
      handleClick,
      getStyle,
      getIconSize,
      getBorder,
      getSize,
      getWeight,
      getSubSize,
      getSubTitleStyle,
      getRound,
      getInset,
      getDescStyle,
      getColor,
      getTitleColor,
    }
  },
})
</script>
<style lang="scss" scoped>
.cell {
  position: relative;
  display: flex;
  line-height: 40rpx;
  padding: 28rpx 24rpx;
  background: $--bg-content-c;
  border-radius: 12rpx;
  font-size: 28rpx;
  box-sizing: border-box;
  margin: 16rpx 24rpx;
  &--shadowable {
    box-shadow: 0 2rpx 14rpx #edeef1;
  }
  .bold {
    font-weight: bold;
    color: $--font-primary-c !important;
  }
  &__inner {
    position: relative;
    width: 100%;
    z-index: 2;
  }
  &__icon {
    margin-right: 16rpx;
    position: relative;
    display: flex;
  }
  &__sub-title-icon {
    margin-left: 10rpx;
  }
  &__label {
    font-size: 24rpx;
    font-weight: bold;
    margin-right: 32rpx;
    position: relative;
    &--tip {
      padding-left: 13rpx;
      &::before {
        content: '';
        position: absolute;
        left: 0;
        top: 50%;
        transform: translateY(-50%);
        width: 5rpx;
        height: 27rpx;
        background: linear-gradient(180deg, #f13131 0%, rgba(255, 188, 92, 0.1) 100%);
        border-radius: 2rpx;
      }
    }
  }
  &__title-group {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;

    .title {
      line-height: 40rpx;
      display: flex;
      color: #748da7;
    }
    .center {
      flex: 1;
      min-width: 0;
      padding-right: 16rpx;
      position: relative;
      z-index: 2;
      &--right {
        padding-right: 0rpx;
      }
    }
    .sub {
      padding: 0 8rpx;
    }
    .sub-title {
      margin-top: 8rpx;
      line-height: 28rpx;
      transform-origin: left center;
      color: $--font-secondary-c;
      @include v-center;
      &--sm {
        font-size: 24rpx;
      }
    }
  }
  &__desc {
    display: inline-block;
    text-align: right;

    .desc {
      color: $--font-secondary-c;
      // @include single-line-text-overflow;
      max-width: 500rpx;
    }
    .sub-desc {
      margin-top: 8rpx;
      line-height: 28rpx;
      transform-origin: left center;
      color: $--font-secondary-c;
    }
  }
  &::before {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 100%;
    height: 100%;
    background-color: #000;
    border: inherit;
    border-color: #000;
    border-radius: inherit;
    transform: translate(-50%, -50%);
    opacity: 0;
    content: ' ';
  }
  &::after {
    position: absolute;
    box-sizing: border-box;
    pointer-events: none;
    right: 24rpx;
    bottom: 0;
    left: 24rpx;
    border-bottom: 2rpx solid #f5f6f7;
  }
  &--inset {
    margin-left: 24rpx;
    margin-right: 24rpx;
  }
  &--lg {
    margin-left: 0;
    margin-right: 0;
  }
  &--sub-lg {
    .sub-title {
      font-size: 26rpx;
    }
    .sub-desc {
      font-size: 26rpx;
    }
  }
  &--sub-md {
    .sub-title {
      font-size: 24rpx;
    }
    .sub-desc {
      font-size: 24rpx;
    }
  }
  &--sub-xs {
    .sub-title {
      @include fz20;
    }
    .sub-desc {
      @include fz20;
    }
  }
  &--xs {
    padding: 20rpx 24rpx;
    .cell__icon {
      margin-right: 8rpx;
    }
    .cell__label {
      font-size: 32rpx;
    }
    .title {
      font-size: 28rpx;
    }
    .desc {
      font-size: 32rpx;
      color: #333;
    }
  }
  &--sm {
    line-height: 36rpx;
    padding: 14rpx 24rpx;
    .title {
      font-size: 26rpx;
    }
    .desc {
      font-size: 26rpx;
      color: $--font-primary-c;
    }
  }
  &--md {
    .title {
      font-size: 28rpx;
    }
    .desc {
      font-size: 28rpx;
    }
  }

  &--border {
    &::after {
      content: '';
    }
  }
  &--round {
    border-radius: 70rpx;
  }
  &:last-child {
    &::after {
      display: none;
    }
  }
}
</style>
